////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Filename:    ZombiesVsCheerlead2Guts.cpp								  //
//  Developer:																  //	
//  Create date:                                                              //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Description: This is the class implementation for the slot gut of the     //
//               Australian Slot machine called El Luchador.			      //
//					(client provided by Genesis)							  //	
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//        2014 - Riplife Gaming.  All rights reserved.						  //
////////////////////////////////////////////////////////////////////////////////

#include "ZombiesVsCheerlead2Guts.h"
#include "slotconn.h"
#include "sltsql.h"


ZombiesVsCheerlead2Guts::SpinResult ZombiesVsCheerlead2Guts::m_aLineWinSpinResults[][6] = 
{
// Number of icons:			0			1			2					3					4					5
/* ICON_WILD */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,	EVT_THREE_WILD,		EVT_FOUR_WILD,		EVT_FIVE_WILD		},
/* ICON_PIC1 */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,	EVT_THREE_PIC1,		EVT_FOUR_PIC1,		EVT_FIVE_PIC1		},
/* ICON_PIC2 */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,	EVT_THREE_PIC2,		EVT_FOUR_PIC2,		EVT_FIVE_PIC2		},
/* ICON_PIC3 */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,	EVT_THREE_PIC3,		EVT_FOUR_PIC3,		EVT_FIVE_PIC3		},
/* ICON_PIC4 */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,	EVT_THREE_PIC4,		EVT_FOUR_PIC4,		EVT_FIVE_PIC4		},
/* ICON_ACE */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,	EVT_THREE_ACE,		EVT_FOUR_ACE,		EVT_FIVE_ACE		},
/* ICON_KING */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,	EVT_THREE_KING,		EVT_FOUR_KING,		EVT_FIVE_KING		},
/* ICON_QUEEN */		{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,	EVT_THREE_QUEEN,	EVT_FOUR_QUEEN,		EVT_FIVE_QUEEN		},
/* ICON_JACK */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,	EVT_THREE_JACK,		EVT_FOUR_JACK,		EVT_FIVE_JACK		},
/* ICON_TEN */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,	EVT_THREE_TEN,		EVT_FOUR_TEN,		EVT_FIVE_TEN		},
/* ICON_NINE */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,	EVT_THREE_NINE,		EVT_FOUR_NINE,		EVT_FIVE_NINE		},
/* ICON_SCATTER */		{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,			EVT_LOSER,			EVT_LOSER			}
};


////////////////////////////////////////////////////////////////////////////
/// ZombiesVsCheerlead2Guts::m_aScatterWinSpinResults
///
/// This array is used to quickly get the SpinResult for the number of
/// icons.  It is indexed by wheel icon and then count.  So to get the
/// SpinResult for 5 Scatter, use the following code snippet:
///
///		SpinResult result = m_aLineWinSpinResults[ ICON_SCATTER ][ 5 ];
///
/// In this example result would be set to EVT_FIVE_SCATTER.
////////////////////////////////////////////////////////////////////////////
ZombiesVsCheerlead2Guts::SpinResult ZombiesVsCheerlead2Guts::m_aScatterWinSpinResults[][6] = 
{
// Number of icons:			0			1						2					3					4					5
/* ICON_WILD */			{	EVT_LOSER,	EVT_LOSER,				EVT_LOSER,			EVT_LOSER,			EVT_LOSER,			EVT_LOSER			},
/* ICON_PIC1 */			{	EVT_LOSER,	EVT_LOSER,				EVT_LOSER,			EVT_LOSER,			EVT_LOSER,			EVT_LOSER			},
/* ICON_PIC2 */			{	EVT_LOSER,	EVT_LOSER,				EVT_LOSER,			EVT_LOSER,			EVT_LOSER,			EVT_LOSER			},
/* ICON_PIC3 */			{	EVT_LOSER,	EVT_LOSER,				EVT_LOSER,			EVT_LOSER,			EVT_LOSER,			EVT_LOSER			},
/* ICON_PIC4 */			{	EVT_LOSER,	EVT_LOSER,				EVT_LOSER,			EVT_LOSER,			EVT_LOSER,			EVT_LOSER			},
/* ICON_ACE */			{	EVT_LOSER,	EVT_LOSER,				EVT_LOSER,			EVT_LOSER,			EVT_LOSER,			EVT_LOSER			},
/* ICON_KING */			{	EVT_LOSER,	EVT_LOSER,				EVT_LOSER,			EVT_LOSER,			EVT_LOSER,			EVT_LOSER			},
/* ICON_QUEEN */		{	EVT_LOSER,	EVT_LOSER,				EVT_LOSER,			EVT_LOSER,			EVT_LOSER,			EVT_LOSER			},
/* ICON_JACK */			{	EVT_LOSER,	EVT_LOSER,				EVT_LOSER,			EVT_LOSER,			EVT_LOSER,			EVT_LOSER			},
/* ICON_TEN */			{	EVT_LOSER,	EVT_LOSER,				EVT_LOSER,			EVT_LOSER,			EVT_LOSER,			EVT_LOSER			},
/* ICON_NINE */			{	EVT_LOSER,	EVT_LOSER,				EVT_LOSER,			EVT_LOSER,			EVT_LOSER,			EVT_LOSER			},
/* ICON_SCATTER */		{	EVT_LOSER,	EVT_SCATTER_NEAR_MISS,	EVT_TWO_SCATTER,	EVT_THREE_SCATTER,	EVT_FOUR_SCATTER,	EVT_FIVE_SCATTER	}
};


static uint8 g_bonusPool_1[5][5] =
{
	// Phase 1
	{ 2, 2, 2, 1, 1 },
	// Phase 2
	{ 2, 2, 2, 2, 1 },
	// Phase 3
	{ 3, 2, 2, 1, 1 },	
	// Phase 4
	{ 4, 2, 2, 2, 2 },
	// Phase 5
	{ 8, 3, 3, 2, 2 }
};

static uint8 g_bonusPool_2[5][5] =
{
	// Phase 1
	{ 3, 2, 2, 1, 1 },
	// Phase 2
	{ 3, 2, 2, 1, 1 },
	// Phase 3
	{ 3, 2, 2, 1, 1 },	
	// Phase 4
	{ 3, 2, 2, 1, 1 },
	// Phase 5
	{ 3, 3, 3, 2, 2 }
};

static uint8 g_bonusPool_3[5][5] =
{
	// Phase 1
	{ 2, 1, 1, 1, 1 },
	// Phase 2
	{ 2, 2, 2, 1, 1 },
	// Phase 3
	{ 2, 2, 1, 1, 1 },	
	// Phase 4
	{ 3, 2, 2, 2, 1 },
	// Phase 5
	{ 4, 3, 2, 1, 1 }
};

static uint8 g_bonusPool_Multiplier[3][6] = 
{
	// Multipliers Pool 1
	{ 8, 4, 3, 1, 1, 1 },
	// Multipliers Pool 2
	{ 8, 3, 2, 1, 1, 1 },
	// Multipliers Pool 3
	{ 8, 3, 2, 1, 1, 1 }
};

static uint8 g_bonusPool_threshold[3][5] = 
{
	// Multipliers Pool 1
	{ 4, 5, 6, 7, 14 },
	// Multipliers Pool 2
	{ 4, 4, 6, 6, 9 },
	// Multipliers Pool 3
	{ 3, 5, 5, 6, 9 }
};

////////////////////////////////////////////////////////////////////////////
/// ZombiesVsCheerlead2Guts::m_aPayLineOffsets
///
/// Declare an array to look up the offset for a reel for each payline.
/// An offset of 0 means that the reel should stop on the middle row,
/// an offset of 1 means the reel should stop on the top row,
/// and an offset of -1 means the reel should stop on the bottom row.
/// So the offset is relative to the middle row, or pay line 1.
////////////////////////////////////////////////////////////////////////////
int8 ZombiesVsCheerlead2Guts::m_aPayLineOffsets[25][5] = 
{
	{  0,  0,  0,  0,  0 },	// Pay line 1
	{  1,  1,  1,  1,  1 },	// Pay line 2
	{ -1, -1, -1, -1, -1 },	// Pay line 3
	{  1,  0, -1,  0,  1 },	// Pay line 4
	{ -1,  0,  1,  0, -1 },	// Pay line 5
	{  1,  1,  0, -1, -1 },	// Pay line 6
	{ -1, -1,  0,  1,  1 },	// Pay line 7
	{  0,  1,  0, -1,  0 },	// Pay line 8
	{  0, -1,  0,  1,  0 },	// Pay line 9
	{  1,  0,  0,  0, -1 },	// Pay line 10
	{ -1,  0,  0,  0,  1 },	// Pay line 11
	{  0,  1,  1,  0, -1 },	// Pay line 12
	{  0, -1, -1,  0,  1 },	// Pay line 13
	{  0,  0,  1,  0, -1 },	// Pay line 14
	{  0,  0, -1,  0,  1 },	// Pay line 15
	{  1,  1,  0, -1,  0 },	// Pay line 16
	{ -1, -1,  0,  1,  0 },	// Pay line 17
	{  0,  1,  0, -1, -1 },	// Pay line 18
	{  0, -1,  0,  1,  1 },	// Pay line 19
	{  1,  1,  1,  0, -1 },	// Pay line 20
	{ -1, -1, -1,  0,  1 },	// Pay line 21
	{  1,  0, -1, -1, -1 },	// Pay line 22
	{ -1,  0,  1,  1,  1 },	// Pay line 23
	{  1,  0,  1,  0,  1 },	// Pay line 24
	{ -1,  0, -1,  0, -1 }	// Pay line 25
};


////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::ZombiesVsCheerlead2Guts()   
///
/// This is the default constructor for the class.
////////////////////////////////////////////////////////////////////////////
ZombiesVsCheerlead2Guts::ZombiesVsCheerlead2Guts()
{
	// If this doesn't compile it means that someone probably added
	// another icon type but did not update the
	// m_aScatterWinSpinResults array. 
	C_ASSERT( countof( m_aScatterWinSpinResults ) == NUM_VALID_ICONS );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::~ZombiesVsCheerlead2Guts()
///
/// Destructor for ZombiesVsCheerlead2Guts. 
////////////////////////////////////////////////////////////////////////////
ZombiesVsCheerlead2Guts::~ZombiesVsCheerlead2Guts()
{
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::getScatterWinResult()   
///
/// @param   spin				The current spin object.
/// @param   testIcon			The scatter icon that we are searching for.
/// @param   scatterPositions	The bit mask for the scatters positions that we find.
///
/// @return	 SpinResult			A payout from the SpinResult enumeration.
///
/// This helper method is used to evaluate the spin for scatters.
////////////////////////////////////////////////////////////////////////////
ZombiesVsCheerlead2Guts::SpinResult ZombiesVsCheerlead2Guts::getScatterWinResult( SlotSpin* spin, uint8 testIcon, int32& scatterPositions ) const
{
	// Declare a local variable to keep up with the icon count.
	uint8 numScatterIcons = 0;

	// Initialize the scatterPositions.
	scatterPositions = 0;

	// Loop through each reel.
  	for( int reel = 0; reel < getReelCount(); reel++ )
	{
		// The position bit for the current icon in case it needs to be stored in a mask.
		uint8 position = reel;

		// Loop through each row in the wheel house.
		for( int row = 0; row < 3; row++ )
		{
			// Get the current stop.
			uint8 stop = relativeWheelPosition( getGameModeId(), reel,
				spin->getStops()[ reel ], row );

			// Get the icon for the current stop.
			uint8 currentIcon = getIcon( getGameModeId(), reel, stop )->iconid;
			
			// If the icon is the one we are looking for...
			if ( currentIcon == testIcon )
			{
				// then increase the icon count
				numScatterIcons++;

				// Set the bit in the position mask for this stop.
				scatterPositions |= 1 << position;
			}

			// Move to the next bit in the position mask.
            position += 5;
		}
	}

	// Use the array to look up the spin result for numScatterIcons.
	return lookupScatterWinSpinResult( testIcon, numScatterIcons );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::evaluateScatterWin()
///
/// This function determines if the current spin wins a scatter payment and
/// adds the scatter.
////////////////////////////////////////////////////////////////////////////
void ZombiesVsCheerlead2Guts::evaluateScatterWin( SlotSpin* spin, SpinResult srScatterResult, int32 scatterPositions )
{
	// If we got the scatter win (or almost got it)
	if ( srScatterResult != EVT_LOSER )
	{
		// Get the base payout for the scatter.
		int32 nPayout = getPayout( srScatterResult )->payoutAmount;

		// Add the payout (with multiplier and bet per line) to the total win for this spin.
		increaseTotalWin( nPayout * getBetPerLine() * getNumLinesBet() );
    
		// Add a scatter to the spin
		spin->addScatter( scatterPositions, nPayout * getBetPerLine() * getNumLinesBet(), 
			              1, false, srScatterResult, 0 );
	}
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::classifyZombiesVsCheerlead2Scatters( SlotSpin* spin, uint8 FeatMultiplier )
///
/// @param   spin       Pointer to the spin with stop data.
///
/// This is an override of the framework method.  
/// It determines if the current spin merits free spins or scatter payments.
///
/// Returns: scatter positions (binary mask)
////////////////////////////////////////////////////////////////////////////
ZombiesVsCheerlead2Guts::SpinResult ZombiesVsCheerlead2Guts::classifyZombiesVsCheerlead2Scatters( SlotSpin* spin )
{	
	// Try for the Random Progressive Jackpot
	tryForJackpot( spin );

	// Declare a local variable to track the scatter positions.
	int32 nScatterPositions = 0;

	// See if there is a scatter.
	SpinResult srResult = getScatterWinResult( spin, ICON_SCATTER, nScatterPositions );

	// Add the scatter, if any.
	evaluateScatterWin( spin, srResult, nScatterPositions );

	return srResult;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::isValidGuts()   
///
/// @return	 bool8      True if gut is valid.    
///
/// This helper method is used to see if the current gut ID is valid.
////////////////////////////////////////////////////////////////////////////
bool8 ZombiesVsCheerlead2Guts::isValidGuts()
{
	// Make sure that the m_aScatterWinSpinResults array has an entry for each reel,
	// and an additional entry in case there are 0 icons on the line.
	ASSERT( countof( m_aScatterWinSpinResults[0] ) == getReelCount( MODE_NORMAL ) + 1 );

	// Now make sure that both game modes have the same number of reels.
	ASSERT( getReelCount( MODE_NORMAL ) == getReelCount( MODE_FREE_SPIN ) );

	// Finally just check to see if the gut is within the right range. GENESIS GAMES: [9000,9500)
    return ( getGutsId() >= 9000 && getGutsId() < 9500 );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::getGameModeMultiplierAndNoteId( uint8& nGameModeMultiplier, uint8& nNoteId )
///
/// @param   nGameModeMultiplier	The multiplier for the game mode.
/// @param   nNoteId				The note ID for the game mode.
///
/// This helper method is used to get the game mode multiplier and note ID.
////////////////////////////////////////////////////////////////////////////
void ZombiesVsCheerlead2Guts::getGameModeMultiplierAndNoteId( uint8& nGameModeMultiplier,
	uint8& nNoteId )
{
	// If we are in free spin mode...
    if ( getGameModeId() == MODE_FREE_SPIN )
    {
		
    }
	// Otherwise...
    else
    {
		// just defer to the base class.
        SlotGuts::getGameModeMultiplierAndNoteId( nGameModeMultiplier, nNoteId );
    }
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::preSpinClassifyResults( SlotSpin* spin )
///
/// @param   spin       Pointer to the spin with stop data.
///
/// This method is overridden when running in debug spins mode to alter the reel stops.
////////////////////////////////////////////////////////////////////////////
void ZombiesVsCheerlead2Guts::preSpinClassifyResults( SlotSpin* spin )
{
	if ((m_subGame->getData(SGIDX_BONUS_GAME_STATE) == 0) && (getGameModeId() != MODE_FREE_SPIN))
	{
		endFeature();
	}
	
	SlotGuts::preSpinClassifyResults(spin);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::postSpinClassifyResults( SlotSpin* spin )
///
/// @param   spin       Pointer to the spin with stop data.
///
/// This method is overridden to see if we can complete the game.
////////////////////////////////////////////////////////////////////////////
void ZombiesVsCheerlead2Guts::postSpinClassifyResults( SlotSpin* spin )
{
	// If we are in a bonus game, the spin cannot complete
	if ( m_subGame->getData(SGIDX_BONUS_GAME_STATE) > 0)
	{
		setGameCanComplete( false );
	}
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::hasSavedGames()
///
/// @param   bool8   True/False indicating if this machine supports saved games.
///
/// This is a framework override to determine if this machine supports saved games.
////////////////////////////////////////////////////////////////////////////
bool8 ZombiesVsCheerlead2Guts::hasSavedGames()
{
	// We support saved games so always return true.
	return true;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::Debug_SetLoserStops( uint8* pStops )
///
/// @param   pStops		The stops to set.
///
/// Base class override, returns a losing spin triggered by the debug tool
////////////////////////////////////////////////////////////////////////////
void ZombiesVsCheerlead2Guts::Debug_SetLoserStops( uint8* pStops )
{
	pStops[0]=1;
	pStops[1]=29;
	pStops[2]=18;
	pStops[3]=16;
	pStops[4]=1;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::getProgressiveValue( )
///
/// Returns current jackpot value for ZombiesAndCheerleaders machine
////////////////////////////////////////////////////////////////////////////
int32 ZombiesVsCheerlead2Guts::getProgressiveValue()
{
   SlotsSQL *slotTracker = (SlotsSQL *) tracker;
   int32 jackpot = 0;

    if ( tracker )
    {
    	slotTracker->lock();
		slotTracker->getJackpot(getJackpotId(), jackpot, getInfo()->forMoney, 1);
    	slotTracker->unlock();
    }

	return jackpot;
}

void ZombiesVsCheerlead2Guts::classifyResult(SlotSpin *spin)
{
	uint8 *classifyPositions = new uint8[spin->getStopCount()];
    uint8 result = 0;

	// First of all, before evaluating lines, classify scatters
	// Classify any scatter pays (implemented as a null function in the base)
	spin->clearScatters();
	SpinResult scatterResult = classifyZombiesVsCheerlead2Scatters(spin);

	// We can have up to two prizes per line in Zombies Vs Cheerleaders 2 (Left to Right + Right to Left), so we are 
	// going to create new lines in order to support this.
	// Lines 1-25	-> Left to Right wins
	// Lines 26-50	-> Right to Left wins
	// We have just created lines from 1 to 25, so we have to create the rest of them:
	for ( uint8 i = getNumLinesBet() + 1; i <= 25; i++)
	{
		spin->addLine(i);
	}
	for ( uint8 i = 26; i <= 50; i++ )
	{
		spin->addLine(i);
	}

	// Before checking lines, if we are in free spins mode, we have to look for infected Wilds
	int32 iWildsInfected = 0;
	if (getGameModeId() == MODE_FREE_SPIN)
	{
		int32 iWildsInfectedBefore = 0;
		do
		{
			iWildsInfectedBefore = iWildsInfected;
			evaluateAddedWilds(spin, iWildsInfected);
		} while (iWildsInfectedBefore != iWildsInfected);

		m_subGame->update(SGDIDX_ADDED_WILDS_CHEERLEADERS, iWildsInfected);
		m_subGame->setServerOnly(SGDIDX_ADDED_WILDS_CHEERLEADERS, false);
	}
	
    /**
     * Go through the played paylines one at a time looking for winners.
     */
    for ( uint8 lineidx = 0; lineidx < getNumLinesBet(); lineidx++ )
    {
		SpinLine *spinLine = spin->getSpinLineAt(lineidx);
		
        /**
         * Iterate the stops to get the classify positions.
         */
        for ( uint8 stopid = 0; stopid < spin->getStopCount(); stopid++ )
        {
            uint8 offsetPosition = getPayline(lineidx+1, stopid)->wheelposition;
            /**
             * Calculate the offset so we are using the proper icon
             * for this payline.
             */
            classifyPositions[stopid] = relativeWheelPosition(getGameModeId(), stopid, spin->getStops()[stopid], offsetPosition);
        }

        // Left to Right
		bool8 bWildSubstitution = false;
		int8 iMultiplier = 1;
		classifyZombiesVsCheerlead2Stops(classifyPositions, false, lineidx, iWildsInfected, result, bWildSubstitution);

        int32 nPayout = getPayout(result)->payoutAmount;
		iMultiplier = bWildSubstitution ? WILD_SUBSTITUTION : 1;
		nPayout = nPayout * getBetPerLine();
        setTotalWin( getTotalWin() + (nPayout*iMultiplier));

		spinLine->basepayoutamount = nPayout;
		spinLine->totalmultiplier =  iMultiplier;
		spinLine->totallinepayoutamount = nPayout*iMultiplier;
		spinLine->jackpot = false;
		spinLine->payouttypeid = result;
		if (bWildSubstitution)
		{
			spinLine->addNote( NOTE_WILD_SUBSTITUTION );
		}

		// Right to Left
		bWildSubstitution = false;
		iMultiplier = 1;
		spinLine = spin->getSpinLineAt(lineidx + 25);
		classifyZombiesVsCheerlead2Stops(classifyPositions, true, lineidx, iWildsInfected, result, bWildSubstitution);
		nPayout = getPayout(result)->payoutAmount;
		iMultiplier = bWildSubstitution ? WILD_SUBSTITUTION : 1;
		nPayout = nPayout * getBetPerLine();
        setTotalWin( getTotalWin() + (nPayout*iMultiplier));

		spinLine->basepayoutamount = nPayout;
		spinLine->totalmultiplier =  iMultiplier;
		spinLine->totallinepayoutamount = nPayout*iMultiplier;
		spinLine->jackpot = false;
		spinLine->payouttypeid = result;
		// Right to Left note
		if (nPayout > 0)
		{
			spinLine->addNote(NOTE_RIGHT_TO_LEFT);
		}
		if (bWildSubstitution)
		{
			spinLine->addNote( NOTE_WILD_SUBSTITUTION );
		}
	}

	//  Did we get feature?
	//  If three or more scatters, player can choose between free games and bonus feature
	if (scatterResult == EVT_THREE_SCATTER ||  scatterResult == EVT_FOUR_SCATTER || scatterResult == EVT_FIVE_SCATTER)
	{
		if  (getGameModeId() == MODE_FREE_SPIN)
		{
			// We are already in free spins mode: Add 5 extra free spins
			incrementFreeSpins( 5 );
			setGameModeId( MODE_FREE_SPIN );
			initFeatureFreeSpins();
		}
		else
		{
			// We are in normal mode, so player can choose
			m_subGame->update( SGIDX_BONUS_GAME_STATE, scPhase1_Choose );
		}
	}						
	
    // Generate the wheel view for reporting
    storeWheelView(spin);

    delete [] classifyPositions;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::classifyZombiesVsCheerlead2Stops()   
///
/// @param   stops      The array of stop positions for the line.
/// @param   bet        The value of the line bet.
/// @param   line       The index of the line.
///
/// This helper method is used to calculate the payout on a line.
////////////////////////////////////////////////////////////////////////////
void ZombiesVsCheerlead2Guts::classifyZombiesVsCheerlead2Stops( uint8* stops, bool8 RightToLeft, uint8 lineidx, int32 iWildsInfected, uint8& rtnresult, bool8& wildSubstitution )
{
	// Calculate wild result. In Zombies Vs Cheerleaders 2 game, this only makes sense in free spin mode
	SpinResult srWildLineWinResult = EVT_LOSER;
	if (getGameModeId() == MODE_FREE_SPIN)
	{
		srWildLineWinResult = getWildsWinResult( stops, RightToLeft, lineidx, iWildsInfected );  
	}

	// Start with the icon on the first (or last) reel.
	uint8 iReel = RightToLeft ? 4 : 0;
	uint8 testIcon = getIcon( getGameModeId(), iReel, stops[iReel] )->iconid;
	// Wild substitution?
	if (getGameModeId() == MODE_FREE_SPIN)
	{
		uint8 row = getRowLineReel(lineidx, iReel);
		if (isInfected(iWildsInfected, iReel, row))
		{
			wildSubstitution = true;
			testIcon = ICON_WILD;
		}
	}

	// See what the spin result is if we used any Wild
	SpinResult srResultWithPossibleSubstitution =
		getLineWinResultWithPossibleSubstitution( stops, testIcon, RightToLeft, lineidx, iWildsInfected, wildSubstitution );

	// Use the largest payout 
    if ( doesWildLineWinPayMore( srWildLineWinResult, srResultWithPossibleSubstitution, wildSubstitution ) )
	{
		// The WILDS by themselves pay out more so use them.
		rtnresult = srWildLineWinResult;
		wildSubstitution = false;
	}
	else
	{
		// Otherwise the result with the substitution (if any) paid more so use it.
		rtnresult = srResultWithPossibleSubstitution;
	}
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::SpinResult ZombiesVsCheerlead2Guts::getWildsWinResult( uint8* stops, uint8 line, int32 addedWilds ) const
///
/// @param   stops			The array of stop positions for the line.
///
/// @return	 SpinResult		A payout from the SpinResult enumeration.
///
/// This helper method is used to calculate the Cauldron line win payout.
////////////////////////////////////////////////////////////////////////////
ZombiesVsCheerlead2Guts::SpinResult ZombiesVsCheerlead2Guts::getWildsWinResult( uint8* stops, bool8 RightToLeft, uint8 lineidx, int32 iWildsInfected )
{
	// Count how many Wilds we have at the beginning of the line.
	// Loop through the remaining reels until the streak is over
	uint8 iNumIcons = 0;
	int8 iReelStart = 0;
	int8 iReelEnd = 5;
	int8 iIncrement = 1;
	if (RightToLeft)
	{
		iReelStart = 4;
		iReelEnd = -1;
		iIncrement = -1;
	}
	for ( int8 i = iReelStart; i != iReelEnd; i = i+iIncrement, iNumIcons++ )
    {
		// If this icon is not a WILD
		int32 iIconID = getIcon( getGameModeId(), i, stops[i] )->iconid;
		if ( iIconID != ICON_WILD )
		{
			// Wild substitution?
			uint8 row = getRowLineReel(lineidx, i);
			if (!isInfected(iWildsInfected, i, row))
			{
				break;
			}
		}
    }

	// Use the array to look up the spin result for iNumIcons Wilds.
	return lookupLineWinSpinResult( ICON_WILD, iNumIcons );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::SpinResult ZombiesVsCheerlead2Guts::getLineWinResultWithPossibleSubstitution( uint8* stops, uint8 testIcon, int32 addedWilds ) const
///
/// @param   stops			The array of stop positions for the line.
/// @param   testIcon		The icon we are looking for, typically the first icon on the line.
/// @param   bSubstitution	An output parameter that is set if a subsitution is used.
///
/// @return	 SpinResult		A payout from the SpinResult enumeration.
///
/// This helper method is used to calculate the line win payout with a possible substitution.
////////////////////////////////////////////////////////////////////////////
ZombiesVsCheerlead2Guts::SpinResult ZombiesVsCheerlead2Guts::getLineWinResultWithPossibleSubstitution(
	uint8* stops, uint8 testIcon, bool8 RightToLeft, uint8 lineidx, int32 iWildsInfected, bool8& wildSubstitution )
{
	// Loop through the remaining reels until the streak is over
	uint8 iNumIcons = 1;
	int8 iReelStart = 1;
	int8 iReelEnd = 5;
	int8 iIncrement = 1;
	if (RightToLeft)
	{
		iReelStart = 3;
		iReelEnd = -1;
		iIncrement = -1;
	}
	for ( int8 i = iReelStart; i != iReelEnd; i = i+iIncrement, iNumIcons++ )
    {
		// See what this icon is.
		uint8 currentIcon = getIcon( getGameModeId(), i, stops[i] )->iconid;

		// If the current icon is a Cauldron (Wild)...
		if ( currentIcon == ICON_WILD )
		{
			// then use it as a substitution symbol and continue on.
			wildSubstitution = true;
			continue;
		}
		// If the current icon is substitued by a WILD
		else
		{			
			if (getGameModeId() == MODE_FREE_SPIN)
			{
				uint8 row = getRowLineReel(lineidx, i);
				if (isInfected(iWildsInfected, i, row))
				{
					wildSubstitution = true;
					continue;
				}
			}
		}
		
		// Otherwise if the test icon is a WILD
		if ( testIcon == ICON_WILD )
		{
			// We have now found our first icon that is not a Wild.  All
			// of the rest of the icons will have to match this one now for the
			// streak to continue, so change our test icon.
			testIcon = currentIcon;
			continue;
		}

		// If the current icon is not the test icon...
        if ( currentIcon != testIcon )
        {
			break;											
        }
    }

	if (testIcon == ICON_WILD)
	{
		// We are not looking for wilds here. So this is a PIC1 or PIC2 payout (which are the ones becoming wild)
		uint8 auxIcon;
		if (!RightToLeft)
		{
			auxIcon = getIcon( getGameModeId(), 0, stops[0] )->iconid;
		}
		else
		{
			auxIcon = getIcon( getGameModeId(), 4, stops[0] )->iconid;
		}
		if (auxIcon == ICON_PIC1)
			testIcon = ICON_PIC1;
		else
			testIcon = ICON_PIC2;
	}

	// Use the array to look up the spin result for iNumIcons testIcons.
  	return lookupLineWinSpinResult( testIcon, iNumIcons );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 bool ZombiesVsCheerlead2Guts::doesWildLineWinPayMore( SpinResult srWilds, SpinResult srOther ) const
///
/// @param   srWilds		The spin result to calculate the Wilds payout for.
/// @param   srOther		The spin result to calculate the other payout for.
///
/// @return	 bool			True if the Cauldron win is larger.
///
/// This helper method is used to see which payout is larger.
////////////////////////////////////////////////////////////////////////////
bool ZombiesVsCheerlead2Guts::doesWildLineWinPayMore( SpinResult srWilds, SpinResult srOther, bool8 bSubstitution ) const
{
	// Lookup the payout for the Cauldron line win.
	long nWildsLineWinPayout = getPayout( srWilds )->payoutAmount;

	// Lookup the payout for the other line win.
	uint8 iMultiplier = bSubstitution ? WILD_SUBSTITUTION : 1;
	long nOtherLineWinPayout = getPayout( srOther )->payoutAmount * iMultiplier;

	// Return true if the WILD payout is equal or bigger.
    return ( nWildsLineWinPayout >= nOtherLineWinPayout );
}

////////////////////////////////////////////////////////////////////////////
/// @fn		ZombiesVsCheerlead2Guts::tryForJackpot()
///
///	This function tries to win the jackpot and adds the scatter if we hit
/// the jackpot.
////////////////////////////////////////////////////////////////////////////
void ZombiesVsCheerlead2Guts::tryForJackpot( SlotSpin* spin )
{
	// If we are in the first paid spin (NOT a bonus spin)...
	if ( getGameModeId() == MODE_NORMAL ) 
	{
		// then try for the Random Progressive Jackpot
		// If we hit the jackpot...
		if ( getRandomProgressiveJackpotResult( getNumLinesBet() ) || m_bForceRandomJackpot)
		{
			// then add a jackpot scatter to the spin.
			spin->addScatter( 0,
				getPayout( EVT_RANDOM_PROGRESSIVE_WINNER )->payoutAmount, 1,
				true, EVT_RANDOM_PROGRESSIVE_WINNER, 0 );
		}
    }

	// In third party games (API) we include the jackpot in every spin so that they can update it.
	// If no jackpot, they have not won the jackpot
	setJackpotAmount( getProgressiveValue() );
}


void ZombiesVsCheerlead2Guts::initDebugFunctionMap()
{
	SlotGuts::initDebugFunctionMap();	
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 ZombiesVsCheerlead2Guts::processClientData()
///
/// @param   bonusGameType      The current type of bonus game.
/// @param   bonusDataCount     The number of integers passed from the client.
/// @param   bonusData			An array of integers passed from the client.
/// 
/// This is an override of the framework method.
/// 
////////////////////////////////////////////////////////////////////////////
bool8
ZombiesVsCheerlead2Guts::processClientData( uint8 bonusGameType, int32 bonusDataCount, int32 *bonusData )
{
	// Start by assuming that we do not need to reply to this message
	bool8 bReply = false;

	if ( m_subGame->getData(SGIDX_BONUS_GAME_STATE) == scPhase1_Choose )
	{
		if (bonusDataCount == 1 && bonusData != NULL)
		{
			int32 nChosenOption = *bonusData;
			if (nChosenOption == 1)
			{
				// Player has chosen free spins
				incrementFreeSpins( 5 );
				setGameModeId( MODE_FREE_SPIN );								
				
				// Bonus finishes here
				m_subGame->update(SGIDX_BONUS_GAME_STATE, scNone);
				setGameCanComplete( true );				
			}
			else
			{
				// Player has chosen Cheerleader Escape Bonus Feature, move to next phase
				m_subGame->update(SGIDX_BONUS_GAME_STATE, scPhase2_Escape);
				initFeatureEscape();
			}

			bReply = true;
		}
	} 
	else
	{
		// Bonus Game State: scPhase2_Escape (Cheerleader Escape Bonus Feature)
		if (bonusDataCount == 1 && bonusData != NULL)
		{
			uint8 iPhase = m_subGame->getData(SGDIDX_ESCAPE_PHASE);	
			if (iPhase == 6)
			{
				// Last phase: multiplier
				initFeatureEscapePhase(6);
				
				// Apply multiplier and calculate total win due to multiplier
				uint8 iMultiplier = m_subGame->getData(SGDIDX_ESCAPE_TOTAL_PHASE);
				int32 iTotalWin = 0;
				if (iMultiplier > 1)
				{
					iTotalWin = applyFeatureEscapeMultiplier(iMultiplier);
				}

				// Add bonus				
				uint8 iIndex = 15; // 15 rounds before, 5 roundx * 3 picks
				addBonusGame(BT_ESCAPE_MULTIPLIER, iIndex, iTotalWin, iMultiplier, iTotalWin, 0); 
			}
			else
			{
				// Phase 1-5
				uint8 iPicksRemaining = m_subGame->getData(SGDIDX_ESCAPE_PICKS_REMAINING);
				uint8 iEscapeTotalPhase = m_subGame->getData(SGDIDX_ESCAPE_TOTAL_PHASE);
				uint8 iAmountPick = 0;
				uint8 iIndex = ((iPhase-1)*3) + (3-iPicksRemaining);
				
				switch(iPicksRemaining)
				{
					case 3: initFeatureEscapePhase(iPhase);
							iEscapeTotalPhase = 0;
							m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK1, false);
							iAmountPick = m_subGame->getData(SGDIDX_ESCAPE_PICK1);
							iPicksRemaining = 2;
							break;
					case 2: m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK2, false);
						    iAmountPick = m_subGame->getData(SGDIDX_ESCAPE_PICK2);						
							iPicksRemaining = 1;
							break;
					case 1: m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK3, false);
						    iAmountPick = m_subGame->getData(SGDIDX_ESCAPE_PICK3);				
							uint8 iPool = m_subGame->getData(SGDIDX_ESCAPE_POOL);
							if ((iEscapeTotalPhase + iAmountPick) >= g_bonusPool_threshold[iPool-1][iPhase-1])
							{
								// Over threshold? next phase
								iPicksRemaining = iPhase == 5 ? 1 : 3;
								iPhase++;
							}
							else
							{
								// Bonus finishes here
								m_subGame->update(SGIDX_BONUS_GAME_STATE, scNone);
								setGameCanComplete( true );				
							}
							break;
				}

				// Add bonus
				int32 nBetPerLine = m_subGame->getData(SGIDX_BET_PER_LINE);
				int32 nLinesBet = m_subGame->getData(SGIDX_NUM_LINES_BET);
				int32 nBonusAmount = iAmountPick * nBetPerLine * nLinesBet;
				addBonusGame(BT_ESCAPE_FEATURE, iIndex, nBonusAmount, 1, nBonusAmount, 0); 

				iEscapeTotalPhase += iAmountPick;
				m_subGame->update(SGDIDX_ESCAPE_TOTAL_PHASE, iEscapeTotalPhase);				
				m_subGame->update(SGDIDX_ESCAPE_PICKS_REMAINING, iPicksRemaining);
				m_subGame->update(SGDIDX_ESCAPE_PHASE, iPhase);
			}
				
			bReply = true;			
		}
	} 
		
	return bReply;
}


void ZombiesVsCheerlead2Guts::initFeatureEscapePhase(uint8 Phase)
{
	m_subGame->update(SGDIDX_ESCAPE_PHASE, Phase);
	
	if (Phase == 6)
	{
		m_subGame->update(SGDIDX_ESCAPE_PICKS_REMAINING, 0);
		
		uint8 iPool = m_subGame->getData(SGDIDX_ESCAPE_POOL);
		uint8 iAuxPool[6];	
		for (uint8 i=0; i<6; i++)
			iAuxPool[i] = g_bonusPool_Multiplier[iPool-1][i];

		// Disorder pool
		for(uint8 i=0; i<6; i++)
		{
			int32 iAux = iAuxPool[i];
		
			// Choose a value to swap with
			uint8 iRandomPosition = getrand() % 6;
		
			// Swap the values
			iAuxPool[i] = iAuxPool[iRandomPosition];
			iAuxPool[iRandomPosition] = iAux;
		}

		// Generate pick, just one (multiplier)
		uint8 iRandom = getrand() % 6;
		m_subGame->update(SGDIDX_ESCAPE_TOTAL_PHASE, iAuxPool[iRandom]);
		
		m_subGame->setServerOnly(SGDIDX_ADDED_WILDS_CHEERLEADERS, true);
		m_subGame->setServerOnly(SGDIDX_ESCAPE_PHASE, false);
		m_subGame->setServerOnly(SGDIDX_ESCAPE_PICKS_REMAINING, false);
		m_subGame->setServerOnly(SGDIDX_ESCAPE_TOTAL_PHASE, false);
		m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK1, true);
		m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK2, true);
		m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK3, true);
		m_subGame->setServerOnly(SGDIDX_ESCAPE_POOL, true);

		// Bonus finishes here
		m_subGame->update(SGIDX_BONUS_GAME_STATE, scNone);
		setGameCanComplete( true );				
	}
	else
	{
		uint8 iPool = m_subGame->getData(SGDIDX_ESCAPE_POOL);
		
		// Get values from the corresponding pool
		uint8 *iPoolPointer;
		if (iPool == 1)
			iPoolPointer = g_bonusPool_1[Phase-1];
		else if (iPool == 2)
			iPoolPointer = g_bonusPool_2[Phase-1];
		else
			iPoolPointer = g_bonusPool_3[Phase-1];
		
		uint8 iAuxPool[5];	
		for (uint8 i=0; i<5; i++)
			iAuxPool[i] = iPoolPointer[i];

		// Disorder pool
		for(uint8 i=0; i<5; i++)
		{
			int32 iAux = iAuxPool[i];
		
			// Choose a value to swap with
			uint8 iRandomPosition = getrand() % 5;
		
			// Swap the values
			iAuxPool[i] = iAuxPool[iRandomPosition];
			iAuxPool[iRandomPosition] = iAux;
		}

		// Generate 3 picks from path: choose three random values from disordered pool
		uint8 iRandom1 = getrand() % 5;
		uint8 iRandom2 = getrand() % 5;
		uint8 iRandom3 = getrand() % 5;
		while (iRandom2 == iRandom1){
			iRandom2 = getrand() % 5;
		}
		while ((iRandom3 == iRandom2) || (iRandom3 == iRandom1)){
			iRandom3 = getrand() % 5;
		}

		m_subGame->update(SGDIDX_ESCAPE_PICK1, iAuxPool[iRandom1]);
		m_subGame->update(SGDIDX_ESCAPE_PICK2, iAuxPool[iRandom2]);
		m_subGame->update(SGDIDX_ESCAPE_PICK3, iAuxPool[iRandom3]);
		m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK1, true);
		m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK2, true);
		m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK3, true);

		m_subGame->update(SGDIDX_ESCAPE_TOTAL_PHASE, 0);
		m_subGame->setServerOnly(SGDIDX_ESCAPE_TOTAL_PHASE, false);
	}
}

void ZombiesVsCheerlead2Guts::initFeatureFreeSpins()
{
	// Just one of them is important here: added Wilds
	m_subGame->update(SGDIDX_ADDED_WILDS_CHEERLEADERS, 0);
	m_subGame->setServerOnly(SGDIDX_ADDED_WILDS_CHEERLEADERS, false);

	// The rest of them are not sent during free spins
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PHASE, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PICKS_REMAINING, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_TOTAL_PHASE, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK1, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK2, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK3, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_POOL, true);
}

void ZombiesVsCheerlead2Guts::initFeatureEscape()
{
	// Just one of them is important here: added Wilds
	m_subGame->update(SGDIDX_ADDED_WILDS_CHEERLEADERS, 0);
	m_subGame->setServerOnly(SGDIDX_ADDED_WILDS_CHEERLEADERS, true);

	// First phase, 3 picks remaining
	m_subGame->update(SGDIDX_ESCAPE_PHASE, 1);
	m_subGame->update(SGDIDX_ESCAPE_PICKS_REMAINING, 3);
	m_subGame->update(SGDIDX_ESCAPE_TOTAL_PHASE, 0);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PHASE, false);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PICKS_REMAINING, false);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_TOTAL_PHASE, false);

	// We have to choose a pool
	uint8 iPool = getRandomValueFromProbabilityTable( PT_ESCAPE_POOL );
	m_subGame->update(SGDIDX_ESCAPE_POOL, iPool);
	
	// The rest of them, hidden at this point
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK1, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK2, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK3, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_POOL, true);
}

void ZombiesVsCheerlead2Guts::endFeature()
{
	// All of them hidden
	m_subGame->update(SGDIDX_ADDED_WILDS_CHEERLEADERS, 0);
	m_subGame->update(SGDIDX_ADDED_WILDS_CHEERLEADERS, 0);
	m_subGame->update(SGDIDX_ESCAPE_PHASE, 0);
	m_subGame->update(SGDIDX_ESCAPE_PICKS_REMAINING, 0);
	m_subGame->update(SGDIDX_ESCAPE_TOTAL_PHASE, 0);
	m_subGame->update(SGDIDX_ESCAPE_PICK1, 0);
	m_subGame->update(SGDIDX_ESCAPE_PICK2, 0);
	m_subGame->update(SGDIDX_ESCAPE_PICK3, 0);
	m_subGame->update(SGDIDX_ESCAPE_POOL, 0);

	// The rest of them are not sent during free spins
	m_subGame->setServerOnly(SGDIDX_ADDED_WILDS_CHEERLEADERS, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PHASE, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PICKS_REMAINING, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_TOTAL_PHASE, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK1, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK2, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_PICK3, true);
	m_subGame->setServerOnly(SGDIDX_ESCAPE_POOL, true);
}

int32 ZombiesVsCheerlead2Guts::applyFeatureEscapeMultiplier(uint8 iMultiplier)
{
	SlotSpin *spin = getSlotSpin();
	int32 iTotalWin = 0;

	// We have to go through the previous bonus games, applying the multiplier 
	for ( uint8 bonusGameIndex = 0; bonusGameIndex < spin->getNumBonusGames(); bonusGameIndex++ )
    {
		BonusGame* pBonusGame = spin->getBonusGame( bonusGameIndex );

		if (pBonusGame->basepayoutamount > 0)
		{
			//pBonusGame->totalmultiplier = iMultiplier;
			//pBonusGame->totalbonuspayoutamount = pBonusGame->basepayoutamount * iMultiplier;

			iTotalWin += (iMultiplier-1) * pBonusGame->basepayoutamount;
			//increaseTotalWin(iTotalWin);
		}
	}

	return iTotalWin;
}

void ZombiesVsCheerlead2Guts::evaluateAddedWilds(SlotSpin* spin, int32& iWildsInfected)
{
	// We go through the spin result, looking for iIconID symbols to become wilds
	for(int reel = 0; reel < getReelCount(); reel++ )
	{
		// Loop through each row in the wheel house.
		for( int row = 0; row < 3; row++ )
		{
			// Get the current stop.
			uint8 stop = relativeWheelPosition( getGameModeId(), reel,
				spin->getStops()[ reel ], row );

			// Get the icon for the current stop.
			uint8 currentIcon = getIcon( getGameModeId(), reel, stop )->iconid;

			if (currentIcon == ICON_WILD || isInfected(iWildsInfected, reel, row)) 
			{
				// Infect adyacent icons
				for (int8 reelAux=reel-1; reelAux<=reel+1; reelAux++)
				{
					if (reelAux >=0 && reelAux <5)
					{
						for (int8 rowAux=row-1; rowAux<=row+1; rowAux++)
						{
							if (rowAux>=0 && rowAux<3)
							{
								// Get the current stop.
								uint8 stopAux = relativeWheelPosition( getGameModeId(), reelAux,
											spin->getStops()[ reelAux ], rowAux );

								// Get the icon for the current stop.
								uint8 currentIconAux = getIcon( getGameModeId(), reelAux, stopAux )->iconid;

								if (currentIconAux == ICON_PIC1 || currentIconAux == ICON_PIC2)
								{
									// Cheerleader adjacent to a Zombie... Infection!!!									
									iWildsInfected |= 1 << (reelAux + rowAux*5);
								}
							}
							
						}
					}
				}			
			}			
		}
	}
}

bool8 ZombiesVsCheerlead2Guts::isInfected(int32 iWildsInfected, uint8 reel, uint8 row)
{
	int32 iPosition = 1 << (row * 5 + reel);

	bool8 bReturn = (iWildsInfected & iPosition) > 0;
	
	return bReturn;
}